/* Copyright 2011 Gilberto Pacheco Gallegos.
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
 * this file except in compliance with the License. You may obtain a copy of the
 * License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software distributed
 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
 * language governing permissions and limitations under the License.  */
package net.ramptors.dominiobd.client.grupos;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.cellview.client.DataGrid;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ResizeComposite;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;
import com.google.web.bindery.event.shared.UmbrellaException;
import java.util.Collections;
import java.util.List;
import net.ramptors.dominiobd.client.ServicioGrupos;
import net.ramptors.dominiobd.client.ServicioGruposAsync;
import net.ramptors.dominiobd.client.entity.Grupo;

/**
 * @author Gilberto Pacheco Gallegos
 */
public class AbccGrupos extends ResizeComposite {
  private static AbccGruposUiBinder uiBinder = GWT.create(AbccGruposUiBinder.class);
  interface AbccGruposUiBinder extends UiBinder<Widget, AbccGrupos> {
  }
  protected Grupo modelo;
  private final ServicioGruposAsync proxyServicio = GWT.create(ServicioGrupos.class);
  private final SingleSelectionModel<Grupo> modeloDeSeleccion =
      new SingleSelectionModel<Grupo>();
  {
    modeloDeSeleccion.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
      @Override
      public void onSelectionChange(final SelectionChangeEvent evento) {
        cambioDeSeleccion();
      }
    });
  }
  @UiField
  protected InlineLabel etiquetaTitulo;
  @UiField
  protected TextBox textoId;
  @UiField
  protected TextBox textoDescripcion;
  @UiField(provided = true)
  DataGrid<Grupo> listado = new DataGrid<Grupo>();
  {
    listado.setSelectionModel(modeloDeSeleccion);
    listado.setEmptyTableWidget(new Label("No hay grupos registrados."));
    listado.addColumn(new TextColumn<Grupo>() {
      @Override
      public String getValue(Grupo objeto) {
        return objeto.getId();
      }
    }, "Identificador");
    listado.addColumn(new TextColumn<Grupo>() {
      @Override
      public String getValue(Grupo objeto) {
        return objeto.getDescripcion();
      }
    }, "Descripción");
  }
  public AbccGrupos() {
    initWidget(uiBinder.createAndBindUi(this));
  }
  public void actualiza() {
    nuevo();
    buscaTodoDeFormaAsincrona();
  }
  @UiHandler("botonGuardar")
  void clicEnBotonGuardar(final ClickEvent evento) {
    guarda();
  }
  @UiHandler("botonEliminar")
  void clicEnBotonEliminar(final ClickEvent evento) {
    elimina();
  }
  @UiHandler({"botonNuevo", "botonCancelar"})
  void clicEnBotonNuevoOCancelar(final ClickEvent evento) {
    nuevo();
  }
  private void limpiaSeleccion() {
    final Grupo seleccion = modeloDeSeleccion.getSelectedObject();
    if (seleccion != null) {
      modeloDeSeleccion.setSelected(seleccion, false);
    }
  }
  private void cambioDeSeleccion() {
    final Grupo seleccion = modeloDeSeleccion.getSelectedObject();
    if (seleccion != null) {
      edita(seleccion);
    }
  }
  private void nuevo() {
    etiquetaTitulo.setText("Nuevo Grupo");
    textoId.setReadOnly(false);
    limpiaSeleccion();
    muestra(new Grupo());
  }
  private void edita(final Grupo objeto) {
    final Grupo copia =
        new Grupo(objeto.getId(), objeto.getVersion(), objeto.getDescripcion());
    etiquetaTitulo.setText(objeto.getId() + " - Editar Grupo");
    textoId.setReadOnly(true);
    muestra(copia);
  }
  private void guarda() {
    leeModelo();
    if (modeloDeSeleccion.getSelectedObject() == null) {
      agregaDeFormaAsincrona();
    } else {
      modificaDeFormaAsincrona();
    }
  }
  private void elimina() {
    final Grupo seleccion = modeloDeSeleccion.getSelectedObject();
    if (seleccion != null && confirmaEliminarObjeto(seleccion)) {
      eliminaDeFormaAsincrona();
    }
  }
  private void muestra(final Grupo objeto) {
    this.modelo = objeto;
    textoId.setValue(objeto.getId());
    textoDescripcion.setValue(objeto.getDescripcion());
  }
  private void leeModelo() {
    modelo.setId(textoId.getValue().trim());
    modelo.setDescripcion(textoDescripcion.getValue().trim());
  }
  private void buscaTodoDeFormaAsincrona() {
    proxyServicio.buscaTodo(new AsyncCallback<List<Grupo>>() {
      @Override
      public void onFailure(final Throwable caught) {
        procesa(caught);
      }
      @Override
      public void onSuccess(final List<Grupo> lista) {
        listado.setRowData(lista);
      }
    });
  }
  private void agregaDeFormaAsincrona() {
    proxyServicio.agrega(modelo, new AsyncCallback<Grupo>() {
      @Override
      public void onFailure(final Throwable caught) {
        procesa(caught);
      }
      @Override
      public void onSuccess(final Grupo resultado) {
        actualiza();
      }
    });
  }
  private void modificaDeFormaAsincrona() {
    proxyServicio.modifica(modelo, new AsyncCallback<Grupo>() {
      @Override
      public void onFailure(final Throwable caught) {
        procesa(caught);
      }
      @Override
      public void onSuccess(final Grupo resultado) {
        actualiza();
      }
    });
  }
  private void eliminaDeFormaAsincrona() {
    proxyServicio.elimina(modelo.getId(), new AsyncCallback<Void>() {
      @Override
      public void onFailure(final Throwable caught) {
        procesa(caught);
      }
      @Override
      public void onSuccess(final Void resultado) {
        actualiza();
      }
    });
  }
  private boolean confirmaEliminarObjeto(final Grupo objeto) {
    final String mensaje = "¿Realmente desea elminar este grupo?"
        + "\n\nIdentificador: " + objeto.getId()
        + "\nDescripción: " + objeto.getDescripcion()
        + "\n\nNo podrá recuperarlo una vez eliminado."
        + "\n\nPresione Aceptar para eliminarlo o Cancelar para conservarlo.";
    return Window.confirm(mensaje);
  }
  private void procesa(final Throwable t) {
    throw new UmbrellaException(Collections.singleton(t));
  }
}
